import { Button, Checkbox, Input, message, Modal } from "antd";
import {
  PropsWithChildren,
  useEffect,
  useLayoutEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { SvgIcon } from "../../components/SvgIcon";
import markdownStr from "../../mock/markdown-txt";
import { LegalAdviceInput } from "./LegalAdviceInput";
import { SSEChatItem } from "./SSEChatItem";
import { useLegalAdviceStore } from "@/store";
import { Condition } from "@/components/Condition";
import { copyTextToClipboard, randomNumber } from "@/utils";
import {
  fetchUpdateChat,
  fetchUpdateFeedback,
  fetchUploadFile,
  getUserId,
} from "@/api/server/recommend_question";
import {
  AliwangwangOutlined,
  FileAddOutlined,
  FileWordFilled,
  PhoneOutlined,
} from "@ant-design/icons";
import { FileItem } from "./FileItem";
import markdownIt from "markdown-it";

interface ILegalAdviceChatInfoProps {
  className?: string;
  infoKey?: string;
}
export function LegalAdviceChatInfo(
  props: PropsWithChildren<ILegalAdviceChatInfoProps>
) {
  const activeKey = useLegalAdviceStore((state) => state.activeKey);
  const onSendMessage = useLegalAdviceStore((state) => state.onSendMessage);
  const onStopAnswering = useLegalAdviceStore((state) => state.onStopAnswering);
  const setActiveKey = useLegalAdviceStore((state) => state.setActiveKey);
  const appendChatList = useLegalAdviceStore((state) => state.appendChatList);
  const updateChatList = useLegalAdviceStore((state) => state.updateChatList);
  const deleteChatAndReAnswer = useLegalAdviceStore(
    (state) => state.deleteChatAndReAnswer
  );
  const updateLoadingChat = useLegalAdviceStore(
    (state) => state.updateLoadingChat
  );
  const sseChatItemRef = useRef(null);
  const unmounted = useRef(false);
  const [thumbsDownLoading, setThumbsDownLoading] = useState(false);
  const [inputValue, setInputValue] = useState("");
  const [feedbackInput, setFeedbackInput] = useState("");
  const socketRef = useRef<WebSocket>();
  const [feedbackOptions] = useState([
    "法律不正确",
    "不应该使用记忆",
    "不喜欢这种风格",
    "与事实不符",
    "未完全遵循指令",
    "在不应该的情况下提出拒绝",
    "犯懒",
    "不安全或存在问题",
    "其他",
  ]);
  const [showFeedback, setShowFeedback] = useState("");
  const [feedbackArray, setFeedbackArray] = useState([]);
  const list = useLegalAdviceStore((state) => state.chatList);
  const containerRef = useRef<HTMLDivElement>(null);
  const isAnswering = useMemo(() => {
    return list.some((item) => item.loading);
  }, [list]);
  const isLawyer = useMemo(() => {
    return list.some((item) => item.sender === "lawyer");
  }, [list]);

  const onScrollBottom = () => {
    containerRef.current?.scrollTo({
      top: containerRef.current.scrollHeight,
      behavior: "smooth",
    });
  };

  useLayoutEffect(() => {
    onScrollBottom();
  }, [list]);

  const onSubmit = (message: string) => {
    if (!message?.trim()) {
      return;
    }

    if (isLawyer) {
      sendMsg(message);
      appendChatList(message);
    } else {
      onSendMessage(message, activeKey);
    }
  };

  const startOnline = async () => {
    await fetchUpdateChat({
      chat_id: activeKey,
      sender: "lawyer",
      message: "转在线律师成功，后续将由专业的律师为您解答～",
    });
    setActiveKey(activeKey);
  };

  const onThumbsDown = async () => {
    setThumbsDownLoading(true);
    await fetchUpdateFeedback({
      chat_id: activeKey,
      child_chat_id: showFeedback,
      dislike: true,
      like: false,
      dislike_content: feedbackArray
        .concat([feedbackInput])
        .filter((n) => !!n)
        .join(","),
    });
    setFeedbackInput("");
    setFeedbackArray([]);
    setThumbsDownLoading(false);
    setShowFeedback("");
    setActiveKey(activeKey);
  };

  const onRetry = (item) => {
    deleteChatAndReAnswer(item);
  };

  const initWebsocket = () => {
    const md = new markdownIt();
    closeWebsocket();
    const userId = getUserId();
    const protocol = location.protocol.replace("http", "ws");
    socketRef.current = new WebSocket(
      `${protocol}//${location.host}/ws/${userId}`
    );

    // 当连接成功建立时触发
    socketRef.current.onopen = function (event) {
      console.log("WebSocket is open now.");
      // 连接建立后，你可以发送消息到服务器
      // socketRef.current.send("Hello Server!");
    };

    // 当从服务器接收到消息时触发
    socketRef.current.onmessage = function (event) {
      try {
        const data = JSON.parse(event.data);
        if (data?.sender !== "lawyer") {
          return;
        }

        appendChatList({
          key: data.child_chat_id,
          chat_id: data.chat_id,
          message: data.message,
          isMarkdown: true,
          text: md
            .render(data.message.replace(/([^\n])\n([^\n])/g, "$1\n\n$2"))
            ?.trim(),
          sender: data.sender,
        });
      } catch (err) {
        console.log("Message from server ", event.data);
      }
    };

    // 当连接关闭时触发
    socketRef.current.onclose = function (event) {
      if (event.wasClean) {
        console.log(
          "WebSocket connection closed cleanly, code=",
          event.code,
          " reason=",
          event.reason
        );
      } else {
        // e.g. server process killed or network down
        // event.code is usually 1006 in this case
        console.log("WebSocket connection died");
      }
    };

    // 当连接发生错误时触发
    socketRef.current.onerror = function (error) {
      console.log("WebSocket Error: ", error);
    };
  };

  const closeWebsocket = () => {
    socketRef.current?.close();
    socketRef.current = null;
  };

  const sendMsg = (s: string) => {
    socketRef.current.send(
      JSON.stringify({
        chat_id: activeKey,
        sender: "user",
        message: s,
        type: "text",
      })
    );
  };

  useEffect(() => {
    if (isLawyer) {
      initWebsocket();
    }

    return () => {
      closeWebsocket();
    };
  }, [isLawyer]);

  useEffect(() => {
    unmounted.current = false;
    return () => {
      unmounted.current = true;
    };
  }, []);

  const getFileSize = (n) => {
    if (n > Math.pow(2, 30)) {
      return (n / Math.pow(2, 30)).toFixed(2) + "gb";
    } else if (n > Math.pow(2, 20)) {
      return (n / Math.pow(2, 20)).toFixed(2) + "mb";
    } else if (n > Math.pow(2, 10)) {
      return (n / Math.pow(2, 10)).toFixed(2) + "kb";
    } else {
      return n + "b";
    }
  };

  const onUploadFile = () => {
    const input = document.createElement("input");
    input.style.display = "block";
    input.type = "file";

    input.onchange = function (e: any) {
      const file = e.target.files?.[0];
      input.remove();
      console.log("file", file);
      if (!/\.docx$/i.test(file?.name)) {
        message.warning("请上传 docx 文件");
        return;
      }

      appendChatList({
        key: randomNumber(),
        text: file?.name,
        size: getFileSize(file?.size),
        fileData: file,
        status: "wait-upload",
        type: "file",
        sender: "user",
      });
    };
    input.oncancel = function (e) {
      console.log("cancel");
      input.remove();
    };

    input.click();
  };

  const onUploadSuccess = (item: any, filename: string) => {
    updateChatList(item.key, {
      filePath: filename,
      status: "uploaded",
    });

    socketRef.current.send(
      JSON.stringify({
        chat_id: activeKey,
        sender: "user",
        status: "uploaded",
        message: item.text,
        size: item.size,
        type: "file",
      })
    );
  };

  return (
    <>
      <div
        ref={containerRef}
        className="flex-1 min-h-0 overflow-auto scrollBarHide py-[16px]"
      >
        {list?.map((item, i) => {
          const isLast = i === list.length - 1;
          const isLiked = item.like;
          const isDislike = item.dislike;
          let com = (
            <>
              <img src="/images/user.svg" width={24} />
              <pre className="text-[16px] ml-[16px] text-justify break-all rounded-[16px] text-[#333] font-[400] whitespace-pre-wrap">
                {item.text}
              </pre>
            </>
          );

          if (item.loading) {
            com = (
              <SSEChatItem
                message={item.message}
                ref={sseChatItemRef}
                chatId={item.chatId}
                updateLoadingChat={updateLoadingChat}
                onLoading={onScrollBottom}
              />
            );
          } else if (item.type === "file") {
            com = (
              <>
                <img src="/images/user.svg" width={24} />
                <FileItem
                  item={item}
                  onUploadSuccess={(filename) =>
                    onUploadSuccess(item, filename)
                  }
                />
              </>
            );
          } else if (item.isMarkdown) {
            com = (
              <>
                <div className="text-[16px] ml-[16px] text-justify break-all rounded-[16px] text-[#333] font-[400] markdownAnswer markdown-body overflow-hidden">
                  <div className="flex flex-row gap-[16px] items-start relative">
                    <img src="/images/logo-mini.png" width={24} />
                    <Condition condition={!!item.answerType}>
                      <div className="absolute right-0 text-[#878aab] good-badge top-[-10px]">
                        {item.answerType}
                      </div>
                    </Condition>
                    <div
                      className={[
                        "flex-1 min-w-0",
                        !!item.answerType && "mt-[24px]",
                      ]
                        .filter(Boolean)
                        .join(" ")}
                      dangerouslySetInnerHTML={{ __html: item.text }}
                    ></div>
                  </div>
                  <div className="flex flex-row justify-between">
                    <div>
                      <Condition condition={item.stop}>
                        <div className="text-[16px] text-[#b6b6b6] ml-[32px]">
                          回答已停止生成
                        </div>
                      </Condition>
                    </div>
                    <div className="flex flex-row items-center gap-[6px]">
                      <Condition condition={!item.stop && !isLawyer}>
                        <div
                          className="flex flex-row items-center gap-[8px] cursor-pointer"
                          onClick={startOnline}
                        >
                          <AliwangwangOutlined />
                          <span>在线律师</span>
                        </div>
                      </Condition>
                      <Condition condition={!item.stop && !isLawyer}>
                        <span className="mx-[6px] text-[#dcdcdc]">|</span>
                      </Condition>
                      <Condition condition={isLiked && !item.stop}>
                        <SvgIcon
                          className="cursor-pointer"
                          size={20}
                          color="#2C79F1"
                          name="tongyi-thumbsUp-fill"
                          onClick={async () => {
                            await fetchUpdateFeedback({
                              chat_id: activeKey,
                              child_chat_id: item.key,
                              like: false,
                              dislike: false,
                              dislike_content: "",
                            });
                            setActiveKey(activeKey);
                          }}
                        />
                      </Condition>
                      <Condition condition={!isLiked && !item.stop}>
                        <SvgIcon
                          className="cursor-pointer"
                          size={20}
                          name="tongyi-thumbsUp-line"
                          onClick={async () => {
                            await fetchUpdateFeedback({
                              chat_id: activeKey,
                              child_chat_id: item.key,
                              like: true,
                              dislike: false,
                              dislike_content: "",
                            });
                            setActiveKey(activeKey);
                          }}
                        />
                      </Condition>

                      <Condition condition={!isDislike && !item.stop}>
                        <SvgIcon
                          className="cursor-pointer"
                          size={20}
                          name="tongyi-thumbsDown-line"
                          onClick={async () => {
                            setShowFeedback(item.key);
                          }}
                        />
                      </Condition>

                      <Condition condition={isDislike && !item.stop}>
                        <SvgIcon
                          className="cursor-pointer"
                          size={20}
                          name="tongyi-thumbsDown-fill"
                          color="#2C79F1"
                          onClick={async () => {
                            await fetchUpdateFeedback({
                              chat_id: activeKey,
                              child_chat_id: item.key,
                              dislike: false,
                              like: false,
                              dislike_content: "",
                            });
                            setActiveKey(activeKey);
                          }}
                        />
                      </Condition>
                      <Condition condition={!item.stop}>
                        <span className="mx-[6px] text-[#dcdcdc]">|</span>
                      </Condition>
                      <img
                        className="cursor-pointer"
                        src="/images/copy.svg"
                        onClick={() => {
                          copyTextToClipboard(
                            item.stop ? item.text : item.message
                          ).then((res) => {
                            message.success("复制成功！");
                          });
                        }}
                      />
                      {isLast && !item.stop && (
                        <>
                          <span className="mx-[6px] text-[#dcdcdc]">|</span>
                          <div
                            className="flex flex-row items-center"
                            onClick={() => onRetry(item)}
                          >
                            <img
                              className="cursor-pointer"
                              src="/images/refresh.svg"
                            />
                            <div className="cursor-pointer">重新生成</div>
                          </div>
                        </>
                      )}
                    </div>
                  </div>
                </div>
              </>
            );
          } else if (item.sender === "lawyer") {
            com = (
              <>
                <div className="text-[16px] ml-[16px] text-justify break-all rounded-[16px] text-[#333] font-[400] markdownAnswer markdown-body overflow-hidden">
                  <div className="flex flex-row gap-[16px] items-start relative">
                    <img src="/images/logo-mini.png" width={24} />
                    <div
                      className={[
                        "flex-1 min-w-0",
                        !!item.answerType && "mt-[24px]",
                      ]
                        .filter(Boolean)
                        .join(" ")}
                      dangerouslySetInnerHTML={{ __html: item.text }}
                    ></div>
                  </div>
                </div>
              </>
            );
          }

          return (
            <div
              key={item.key}
              className={["flex flex-row chatInfoItem", "items-center"].join(
                " "
              )}
            >
              <div className="w-[56px] flex flex-row justify-center">
                {/* <div className="checkBox">
                  <Checkbox />
                </div> */}
              </div>
              <div className="flex-1 min-w-0 inputInner">{com}</div>
              <div className="w-[40px]"></div>
            </div>
          );
        })}
      </div>
      <div className="py-[20px] px-[76px] relative">
        <div className="frosted"></div>
        <div className="flex flex-row items-center">
          <div className="flex-1 min-w-0 flex flex-row justify-center">
            {isAnswering && (
              <Button
                size="large"
                icon={<SvgIcon name="icon-tingzhihuida_default1" />}
                onClick={() => {
                  console.log(sseChatItemRef.current);
                  const stopTxt = sseChatItemRef.current?.abort();
                  onStopAnswering(stopTxt);
                }}
              >
                停止回答
              </Button>
            )}
          </div>
          <div className="w-[118px]"></div>
        </div>
        <LegalAdviceInput
          disabled={isAnswering}
          value={inputValue}
          // suffixChildren={
          //   isLawyer && (
          //     <Button
          //       type="primary"
          //       size="large"
          //       shape="circle"
          //       onClick={onUploadFile}
          //     >
          //       <FileAddOutlined />
          //     </Button>
          //   )
          // }
          onSubmit={onSubmit}
          onChange={(e) => setInputValue(e)}
        />
      </div>
      <Modal
        title="提供额外的反馈"
        open={!!showFeedback}
        footer={null}
        onCancel={() => {
          setFeedbackInput("");
          setFeedbackArray([]);
          setShowFeedback("");
        }}
      >
        <div className="flex flex-row flex-wrap gap-[16px] py-[8px]">
          {feedbackOptions.map((s) => {
            const findIndex = feedbackArray.findIndex((n) => n === s);
            return (
              <div
                className={[
                  "feedback-item",
                  findIndex >= 0 && "feedback-item-active",
                ]
                  .filter(Boolean)
                  .join(" ")}
                key={s}
                onClick={() => {
                  if (findIndex >= 0) {
                    feedbackArray.splice(findIndex, 1);
                    setFeedbackArray([...feedbackArray]);
                  } else {
                    setFeedbackArray(feedbackArray.concat([s]));
                  }
                }}
              >
                {s}
              </div>
            );
          })}
        </div>
        <div className="mt-[8px]">
          <Input
            value={feedbackInput}
            allowClear
            onChange={(e) => setFeedbackInput(e.target.value)}
            placeholder="（可选）请随意添加特定的细节"
          />
        </div>
        <div className="flex flex-row justify-end mt-[16px]">
          <Button
            onClick={onThumbsDown}
            loading={thumbsDownLoading}
            disabled={feedbackArray.length === 0 && !feedbackInput?.trim()}
            type="primary"
          >
            提交
          </Button>
        </div>
      </Modal>
    </>
  );
}
